package survivalcraft.common;

import java.util.Random;




import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;

import net.minecraft.src.Block;
import net.minecraft.src.BlockContainer;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
import net.minecraft.src.Material;
import net.minecraft.src.MathHelper;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.TileEntity;
import net.minecraft.src.World;
import net.minecraftforge.common.ForgeDirection;

public class BlockCampFire extends BlockContainer {

	public int blockID;

	/**
	 * Is the random generator used by furnace to drop the inventory contents in
	 * random directions.
	 */
	private Random furnaceRand = new Random();

	/** True if this is an active furnace, false if idle */
	private final boolean isActive;

	/**
	 * This flag is used to prevent the furnace inventory to be dropped upon
	 * block removal, is used internally when the furnace block changes from
	 * idle to active and vice-versa.
	 */
	private static boolean keepFurnaceInventory = false;

	private static int idleBlockID = 0;
	private static int activeBlockID = 0;

	// public CampFire(int blockID) {
	// super(blockID, isActive);
	// this.blockID = blockID;
	// this.setBlockName(blockName);
	// LanguageRegistry.addName(this, blockName);

	// this.setCreativeTab(CreativeTabs.tabDecorations);

	// this.setStepSound(soundStoneFootstep);
	// this.setHardness(3.5F);
	// this.setRequiresSelfNotify();
	// this.setTickRandomly(true);

	// this.addCampFireRecipe();
	// }

	protected BlockCampFire(int blockID, boolean isActive) {
		super(blockID, Material.rock);
		this.isActive = isActive;
		this.blockIndexInTexture = 45;
		if (isActive) {
			activeBlockID = blockID;
		} else {
			idleBlockID = blockID;
		}
	}

	/**
	 * Returns the ID of the items to drop on destruction.
	 */
	public int idDropped(int par1, Random par2Random, int par3) {
		return this.idleBlockID;
	}

	/**
	 * Called whenever the block is added into the world. Args: world, x, y, z
	 */
	public void onBlockAdded(World par1World, int x, int y, int z) {
		super.onBlockAdded(par1World, x, y, z);
		this.setDefaultDirection(par1World, x, y, z);
	}

	/**
	 * set a blocks direction
	 */
	private void setDefaultDirection(World par1World, int x, int y, int z) {
		if (!par1World.isRemote) {
			int blockIDFront = par1World.getBlockId(x, y, z - 1);
			int blockIDBehind = par1World.getBlockId(x, y, z + 1);
			int blockIDLeft = par1World.getBlockId(x - 1, y, z);
			int blockIDRight = par1World.getBlockId(x + 1, y, z);
			byte blockFaceDirection = 3;

			if (Block.opaqueCubeLookup[blockIDFront] && !Block.opaqueCubeLookup[blockIDBehind]) {
				blockFaceDirection = 3;
			}

			if (Block.opaqueCubeLookup[blockIDBehind] && !Block.opaqueCubeLookup[blockIDFront]) {
				blockFaceDirection = 2;
			}

			if (Block.opaqueCubeLookup[blockIDLeft] && !Block.opaqueCubeLookup[blockIDRight]) {
				blockFaceDirection = 5;
			}

			if (Block.opaqueCubeLookup[blockIDRight] && !Block.opaqueCubeLookup[blockIDLeft]) {
				blockFaceDirection = 4;
			}

			par1World.setBlockMetadataWithNotify(x, y, z, blockFaceDirection);
		}
	}

	@SideOnly(Side.CLIENT)
	/**
	 * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
	 */
	public int getBlockTexture(IBlockAccess par1IBlockAccess, int x, int y, int z, int side) {
		if (side == 1) {
			return this.blockIndexInTexture + 17;
		} else if (side == 0) {
			return this.blockIndexInTexture + 17;
		} else {
			int blockFaceDirection = par1IBlockAccess.getBlockMetadata(x, y, z);
			return side != blockFaceDirection ? this.blockIndexInTexture : (this.isActive ? this.blockIndexInTexture + 16 : this.blockIndexInTexture - 1);
		}
	}

	@SideOnly(Side.CLIENT)
	/**
	 * A randomly called display update to be able to add particles or other items for display
	 */
	public void randomDisplayTick(World par1World, int x, int y, int z, Random par5Random) {
		if (this.isActive) {
			int var6 = par1World.getBlockMetadata(x, y, z);
			float var7 = (float) x + 0.5F;
			float var8 = (float) y + 0.0F + par5Random.nextFloat() * 6.0F / 16.0F;
			float var9 = (float) z + 0.5F;
			float var10 = 0.52F;
			float var11 = par5Random.nextFloat() * 0.6F - 0.3F;

			if (var6 == 4) {
				par1World.spawnParticle("smoke", (double) (var7 - var10), (double) var8, (double) (var9 + var11), 0.0D, 0.0D, 0.0D);
				par1World.spawnParticle("flame", (double) (var7 - var10), (double) var8, (double) (var9 + var11), 0.0D, 0.0D, 0.0D);
			} else if (var6 == 5) {
				par1World.spawnParticle("smoke", (double) (var7 + var10), (double) var8, (double) (var9 + var11), 0.0D, 0.0D, 0.0D);
				par1World.spawnParticle("flame", (double) (var7 + var10), (double) var8, (double) (var9 + var11), 0.0D, 0.0D, 0.0D);
			} else if (var6 == 2) {
				par1World.spawnParticle("smoke", (double) (var7 + var11), (double) var8, (double) (var9 - var10), 0.0D, 0.0D, 0.0D);
				par1World.spawnParticle("flame", (double) (var7 + var11), (double) var8, (double) (var9 - var10), 0.0D, 0.0D, 0.0D);
			} else if (var6 == 3) {
				par1World.spawnParticle("smoke", (double) (var7 + var11), (double) var8, (double) (var9 + var10), 0.0D, 0.0D, 0.0D);
				par1World.spawnParticle("flame", (double) (var7 + var11), (double) var8, (double) (var9 + var10), 0.0D, 0.0D, 0.0D);
			}
		}
	}

	/**
	 * Returns the block texture based on the side being looked at. Args: side
	 */
	public int getBlockTextureFromSide(int side) {
		return side == 1 ? this.blockIndexInTexture + 17 : (side == 0 ? this.blockIndexInTexture + 17 : (side == 3 ? this.blockIndexInTexture - 1
				: this.blockIndexInTexture));
	}

	/**
	 * Called upon block activation (right click on the block.)
	 */
	public boolean onBlockActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) {
		if (par1World.isRemote) {
			return true;
		} else {
			if (isAboveBlockAir(par1World, x, y, z) && par5EntityPlayer.getHeldItem() != null
					&& (par5EntityPlayer.getHeldItem().getItem() == Item.bow || par5EntityPlayer.getHeldItem().getItem() == Item.flintAndSteel)) {
				par1World.playSoundEffect((double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "fire.ignite", 1.0F, 1.0F);
				if (par5EntityPlayer.getHeldItem().getItem() == Item.bow)
					par5EntityPlayer.getHeldItem().damageItem(100, par5EntityPlayer);
				par1World.setBlockWithNotify(x, y + 1, z, Block.fire.blockID);
				updateFurnaceBlockState(hasFuel(par1World, x, y, z), par1World, x, y, z);

			} else {

				TileEntity tileEntity = par1World.getBlockTileEntity(x, y, z);

				if (tileEntity != null) {
					par5EntityPlayer.displayGUIFurnace((TileEntityCampFire) tileEntity);
				}
			}

			return true;
		}
	}

	/**
	 * Update which block ID the furnace is using depending on whether or not it
	 * is burning
	 */
	public static void updateFurnaceBlockState(boolean par0, World par1World, int x, int y, int z) {
		int var5 = par1World.getBlockMetadata(x, y, z);
		TileEntity var6 = par1World.getBlockTileEntity(x, y, z);
		keepFurnaceInventory = true;

		if (par0 && isAboveBlockFire(par1World, x, y, z)) {
			par1World.setBlockWithNotify(x, y, z, activeBlockID);
		} else {
			par1World.setBlockWithNotify(x, y, z, idleBlockID);
		}

		keepFurnaceInventory = false;
		par1World.setBlockMetadataWithNotify(x, y, z, var5);

		if (var6 != null) {
			var6.validate();
			par1World.setBlockTileEntity(x, y, z, var6);
		}
	}

	/**
	 * Returns a new instance of a block's tile entity class. Called on placing
	 * the block.
	 */
	public TileEntity createNewTileEntity(World par1World) {
		return new TileEntityCampFire();
	}

	/**
	 * Called when the block is placed in the world.
	 */
	public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) {
		int var6 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;

		if (var6 == 0) {
			par1World.setBlockMetadataWithNotify(par2, par3, par4, 2);
		}

		if (var6 == 1) {
			par1World.setBlockMetadataWithNotify(par2, par3, par4, 5);
		}

		if (var6 == 2) {
			par1World.setBlockMetadataWithNotify(par2, par3, par4, 3);
		}

		if (var6 == 3) {
			par1World.setBlockMetadataWithNotify(par2, par3, par4, 4);
		}
	}

	/**
	 * ejects contained items into the world, and notifies neighbours of an
	 * update, as appropriate
	 */
	public void breakBlock(World par1World, int x, int y, int z, int par5, int par6) {
		if (!keepFurnaceInventory) {
			TileEntityCampFire tileEntity = (TileEntityCampFire) par1World.getBlockTileEntity(x, y, z);

			if (tileEntity != null) {
				for (int var8 = 0; var8 < tileEntity.getSizeInventory(); ++var8) {
					ItemStack var9 = tileEntity.getStackInSlot(var8);

					if (var9 != null) {
						float var10 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
						float var11 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
						float var12 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;

						while (var9.stackSize > 0) {
							int var13 = this.furnaceRand.nextInt(21) + 10;

							if (var13 > var9.stackSize) {
								var13 = var9.stackSize;
							}

							var9.stackSize -= var13;
							EntityItem var14 = new EntityItem(par1World, (double) ((float) x + var10), (double) ((float) y + var11),
									(double) ((float) z + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage()));

							if (var9.hasTagCompound()) {
								var14.item.setTagCompound((NBTTagCompound) var9.getTagCompound().copy());
							}

							float var15 = 0.05F;
							var14.motionX = (double) ((float) this.furnaceRand.nextGaussian() * var15);
							var14.motionY = (double) ((float) this.furnaceRand.nextGaussian() * var15 + 0.2F);
							var14.motionZ = (double) ((float) this.furnaceRand.nextGaussian() * var15);
							par1World.spawnEntityInWorld(var14);
						}
					}
				}
			}
		}

		super.breakBlock(par1World, x, y, z, par5, par6);
	}

	public boolean isFireSource(World world, int x, int y, int z, int metadata, ForgeDirection side) {
		return (side == ForgeDirection.UP && hasFuel(world, x, y, z));
		
	}

	private boolean hasFuel(World world, int x, int y, int z) {
		TileEntityCampFire tileEntity = (TileEntityCampFire) world.getBlockTileEntity(x, y, z);
		return tileEntity.isBurning() || tileEntity.isItemFuel(tileEntity.getStackInSlot(1));
	}

	private boolean isAboveBlockAir(World world, int x, int y, int z) {
		return (world.getBlockId(x, y + 1, z) == 0);
	}

	private static boolean isAboveBlockFire(World world, int x, int y, int z) {
		return (world.getBlockId(x, y + 1, z) == 51);
	}

}
